#!/usr/bin/perl -w
# SIMPOW2MAT converts SIMPOW data files into Matlab files
#
# SIMPOW2MAT [OPTIONS] OPTPOW_FILE [DYNPOW_FILE] [FILEOUTPUT]
#
# Author:  Federico Milano
# Date:    02 October 2006
# Version: 0.02
#
#e-mail:   Federico.Milano@uclm.es

use strict;
use Cwd;
use File::Basename;

# -----------------------------------------------------------------------
# variable declaration
# -----------------------------------------------------------------------

my $nargin = 0;
my $verbose = 0;
my $helpmsg = 0;
my $samedir = 1;
my $nodyn = 0;

my ($file, $outfile, $dir);
my $dynfile = '';
my $tempfile = '';
my $outdir = '';

my ($i,$j,$h,$k);

my $nbus = -1;
my $nsw = -1;
my $npv = -1;
my $npq = -1;
my $npg = -1;
my $nsh = -1;
my $ntw = -1;
my $ncv = -1;
my $nsr = -1;
my $nline = -1;
my $ntitle = -1;
my $nsyn = -1;
my $ngen = -1;
my $nexc = -1;
my $type = 0;

my $pbase = 100;
my $lbase = 100;
my $fbase = 60;
my $symod = "N";

my ($format,$title,$firstline,@data,@title,%data,@alter);
my (@kvb,@karea,@kzone,@busname,%nameidx,@vol,@ang);
my (@swbus,@swfi,@swvs,@swqt,@swqb,@swpg,@swtype,@swidx);
my (@pvbus,@genbus,@genname,@pvpg,@pvvs,@pvqt,@pvqb,@pvidx);
my (@pqbus,@pqpl,@pqql,@umin,@umax,@loadstatus,@loadno);
my (@shbus,@vbsh,@psh,@qsh,@shstatus,@shno);
my (%lineno,@busfr,@bustt,@linevb,@tfsb,@no,@linetype);
my (@rest,@reat,@susc,@kt,@ratio,@phas,@imax,@pmax,
    @steps,@stepp,@stepm,@linestatus,@treg,@linefi,
    @linecnode,@lineconv,@linepar,@length,@tapside);
my (%twno,@twsb,@bus1,@bus2,@bus3,@vb1,@vb2,@vb3,
    @r12,@r13,@r23,@x12,@x13,@x23,@twstatus);
my (@synbus,@pbgen,@mstt,@xd,@xq,@xdp,@xqp,@xdb,@xqb,@xl,
    @td0p,@td0b,@tq0p,@tq0b,@gentype,@damp,@gbas,@ra,@pf,@qf,@synvreg);
my (@pgbus,@pqpg,@pqqg,@pgidx);
my (@cvname,@cvidx,@cvidn,@cvudion,@cvdx,@cvdr,%cvidx,@cvbusdc2,
    @cvtyp,@cvio,@cvdi,@cvamin,@cvgmin,@cvbus,@cvbusdc1);
my (@srbus1,@srbus2,@srno,@srtype,@srr,@srl,@srx,@srncon);
my (@exctype,@exccode,@excka,@excta,@excte,@exckf,@exctf,@exctr,@excvrmax,@excvrmin);

# -----------------------------------------------------------------------
# check inputs
# -----------------------------------------------------------------------
$nargin = @ARGV;
$nargin || die "Error: No input data file.\n";

# -----------------------------------------------------------------------
# check options
# -----------------------------------------------------------------------
while ($ARGV[0] =~ /^-/) {
    if ($ARGV[0] =~ /v/) {
	$verbose = 1;
    }
    if ($ARGV[0] =~ /h/) {
	$helpmsg = 1;
    }
    if ($ARGV[0] =~ /d/) {
	$samedir = 0;
    }  
    if ($ARGV[0] =~ /n/) {
	$nodyn = 1;
    }  
    shift(@ARGV);
    $nargin--;
    if ($nargin == 0) { last; }
}

($file,$dir) = fileparse($ARGV[0]);
if (!$dir) { $dir = getcwd(); }
print "Working directory <" . $dir . ">\n";
$title = 'Generic SIMPOW Data File <' . $file . '>';

# -----------------------------------------------------------------------
# help (if requested)
# -----------------------------------------------------------------------
if ($helpmsg) {
    print "\nSIMPOW2PSAT converts SIMPOW data files into PSAT files.\n\n";
    print "simpow2psat <options> fileinput <fileoutput>\n";
    print "  -v   verbose\n";
    print "  -h   print this help and exit\n\n";
    print "Author:   Federico Milano\n";
    print "Date:     01-Nov-2007\n";
    print "Version:  2.0.0\n\n";
    print "E-mail:   Federico.Milano\@uclm.es\n";
    die "\n";
}

# -----------------------------------------------------------------------
# define output file name (if necessary)
# -----------------------------------------------------------------------
if ($nargin == 2 && $ARGV[1] =~ /.dynpow$/) {
    $dynfile = $ARGV[1];
    $nargin = 1;
}

if ($nargin == 2 && $ARGV[1] =~ /.m$/) {
    ($outfile,$outdir) = fileparse($ARGV[1]);
}

if ($nargin == 3) {
    $dynfile = splice(@ARGV,1,1);
    $nargin = 2;
    ($outfile,$outdir) = fileparse($ARGV[1]);
}

if ($nargin == 1) {
    $outfile = $file;
    $outfile =~ s/^d*_*/d_/;
    $outfile =~ s/[^\w\.]/_/g;
    $outfile =~ s/\..+$/.m/;
    $ARGV[1] = $dir . $outfile; 
} elsif ($nargin == 0) {
    die "Error: Input file name is missing.\n";
}

if ($samedir && (!$outdir || $outdir eq "./") && $nargin == 2) {
    $ARGV[1] = $dir . $ARGV[1];
}

# -----------------------------------------------------------------------
# open, store and close OPTPOW file
# -----------------------------------------------------------------------

print "Opening SIMPOW-OPTPOW file <$file>\n";
open(IN,$ARGV[0]) || die "Cannot open $file: $!\n";
@data = <IN>;
close(IN) || die "Cannot close $file: $!\n";

# -----------------------------------------------------------------------
# scan OPTPOW data
# -----------------------------------------------------------------------

# read file header
while (defined($_ = shift(@data))) {
    chomp;
    last if /^\*\*/;
    if (/^\$DISABLE/) { discom(); next; }
    if (/^\$INCLUDE/) { include(); next; }
    $ntitle++;
    $_ =~ s/^\!+//;
    $title[$ntitle] = $_;
}

# read data
while (defined($_ = shift(@data))) {

    next if /^!/;
    if (/^\$DISABLE/) { discom(); next; }
    if (/^\$INCLUDE/) { include(); next; }
    $firstline = "NULL";

    if (/^GENERAL/) {		# System bases
	
	while ($firstline ne "END") {
	    %data = splitdata(0);
	    $pbase = assign("SN",$pbase);
	    $lbase = assign("LBASE",$pbase);
	}

    } elsif (/^NODE/) { # Bus data

	while ($firstline ne "END") {
	    %data = splitdata(1);
	    if ($data{"BUS1"} eq "END") { last; }
	    $nbus++;
	    $busname[$nbus] = $data{"BUS1"};
	    #print $busname[$nbus] . "\n";
	    $kvb[$nbus] = assign("UB",1);
	    $vol[$nbus] = assign("UI",1);
	    $ang[$nbus] = 0.017453*assign("FII",0);
	    $karea[$nbus] = assign("AREA",1);
	    $kzone[$nbus] = assign("REGION",1);
	    $nameidx{$busname[$nbus]} = $nbus;
	}

    } elsif (/^LINE/) {
	
	while ($firstline ne "END") {
	    %data = splitdata(2);
	    if ($data{"BUS1"} eq "END") { last; }
	    $nline++;
	    $busfr[$nline] = $nameidx{$data{"BUS1"}};
	    $bustt[$nline] = $nameidx{$data{"BUS2"}};
	    $linevb[$nline] = $kvb[$busfr[$nline]];
	    $lineno{$data{"BUS1"}.$data{"BUS2"}.assign("NO",1)} = $nline;
	    $no[$nline] = assign("NO",0);
	    $linetype[$nline] = 0;
	    $tfsb[$nline] = $lbase;
	    $h = assign("TYPE",1);
	    if ($h == 0) {
		$rest[$nline] = 0;
		$reat[$nline] = 0.0001;
		$susc[$nline] = 0;
	    } elsif ($h == 6) { # DC LINE
		$rest[$nline] = assign("R",0);
		$reat[$nline] = assign("LL",0.0001);
		$susc[$nline] = 0; 
		$linetype[$nline] = 6;
	    } elsif ($h > 10) { # PER UNIT DATA
		$rest[$nline] = assign("R",0);
		$reat[$nline] = assign("X",0.0001);
		$susc[$nline] = assign("B1",0)+assign("B2",0)+assign("B",0);
	    } else { # OHM UNITS
		$rest[$nline] = assign("R",0)*$lbase/($linevb[$nline]**2);
		$reat[$nline] = assign("X",0.0001)*$lbase/($linevb[$nline]**2);
		$susc[$nline] = assign("B1",0)+assign("B2",0)+assign("B",0);
		$susc[$nline] = $susc[$nline]/$lbase*($linevb[$nline]**2);
	    }
	    $length[$nline] = assign("L",0);
	    if ($length[$nline] > 0) {
		$rest[$nline] = $rest[$nline]*$length[$nline];	
		$reat[$nline] = $reat[$nline]*$length[$nline];	
		$susc[$nline] = $susc[$nline]*$length[$nline];	
	    }
	    $kt[$nline] = 0;
	    $tapside[$nline] = 2;
	    $ratio[$nline] = 0;
	    $phas[$nline] = 0;
	    $imax[$nline] = assign("I1MAX",0)*sqrt(3)*$linevb[$nline]/$lbase;
	    $pmax[$nline] = assign("I2MAX",0)*sqrt(3)*$linevb[$nline]/$lbase;
	    $linestatus[$nline] = status();
	    $steps[$nline] = 0;
	    $stepp[$nline] = 0;
	    $stepm[$nline] = 0;
	    $treg[$nline] = 0;
	    $linefi[$nline] = 0;
	    $linecnode[$nline] = 0;
	    $lineconv[$nline] = 0;
	    $linepar[$nline] = 0;          
	}
	
    } elsif (/^TRANSFORMER/) {

	while ($firstline ne "END") {
	    %data = splitdata(-2);
	    if ($data{"BUS1"} eq "END") { last; }
	    $j = assign("NW",2);
	    if ($j == 2) {
		$nline++;
		$busfr[$nline] = $nameidx{$data{"BUS1"}};
		$bustt[$nline] = $nameidx{$data{"BUS2"}};
		$lineno{$data{"BUS1"}.$data{"BUS2"}.assign("NO",1)} = $nline+1;
		$no[$nline] = assign("NO",0);
		$linetype[$nline] = 1;
		$linevb[$nline] = assign("UN1",$kvb[$busfr[$nline]]);
		$tfsb[$nline] = assign("SN",$lbase);
		$length[$nline] = 0;
		$kt[$nline] = $linevb[$nline]/assign("UN2",$kvb[$bustt[$nline]]);
		$rest[$nline] = assign("ER12",0);
		$reat[$nline] = assign("EX12",0.0001);
		$susc[$nline] = 0;
		$ratio[$nline] = 0;
		$tapside[$nline] = assign("TAPSIDE",2);
		$phas[$nline] = assign("FI",0);
		$imax[$nline] = assign("S1MAX",0)/$lbase;
		$pmax[$nline] = assign("S2MAX",0)/$lbase;
		$steps[$nline] = assign("STEP",0);
		$stepp[$nline] = assign("+NSTEP",0);
		$stepm[$nline] = assign("-NSTEP",0);
		$treg[$nline] = 0;
		$linefi[$nline] = 0;
		$linecnode[$nline] = 0;
		$lineconv[$nline] = 0;
		$linepar[$nline] = 0;          
		$linestatus[$nline] = status();
	    } elsif ($j == 3) {
		$ntw++;
		$twsb[$ntw] = assign("SN",$lbase);
		$bus1[$ntw] = $nameidx{$data{"BUS1"}};
		$bus2[$ntw] = $nameidx{$data{"BUS2"}};
		$bus3[$ntw] = $nameidx{$data{"BUS3"}};
		$twno{$data{"BUS1"}.$data{"BUS2"}.$data{"BUS3"}.assign("NO",1)} = $ntw+1;
		$vb1[$ntw] = assign("UN1",$kvb[$bus1[$ntw]]);
		$vb2[$ntw] = assign("UN2",$kvb[$bus2[$ntw]]);
		$vb3[$ntw] = assign("UN3",$kvb[$bus3[$ntw]]);
		$r12[$ntw] = assign("ER12",0);
		$r13[$ntw] = assign("ER13",0);
		$r23[$ntw] = assign("ER23",0);
		$x12[$ntw] = assign("EX12",0);
		$x13[$ntw] = assign("EX13",0);
		$x23[$ntw] = assign("EX23",0);
		$twstatus[$ntw] = status();
	    }
	}
	
    } elsif (/^CONVERTORS/) {

	while ($firstline ne "END") {
	    %data = splitdata(4);
	    if ($data{"BUS1"} eq "END") { last; }
	    $ncv++;
	    $cvname[$ncv] = $data{"BUS1"};
	    $cvidx{$cvname[$ncv]} = $ncv;
	    $cvbus[$ncv] = $nameidx{$data{"BUS2"}};
	    $cvbusdc1[$ncv] = $nameidx{$data{"BUS3"}};
	    $cvbusdc2[$ncv] = $nameidx{$data{"BUS4"}};
	    $cvidn[$ncv] = $data{"IDN"};
	    $cvudion[$ncv] = $data{"UDION"};
	    $cvdx[$ncv] = assign("DX",0.06);
	    $cvdr[$ncv] = assign("DR",0.006);
	}

    } elsif (/^SREACTORS/) {

	while ($firstline ne "END") {
	    %data = splitdata(2);
	    if ($data{"BUS1"} eq "END") { last; }
	    $nsr++;
	    if ($data{"BUS1"} eq "DCGROUND") {
		$srbus1[$nsr] = -1;      
	    } else {
		$srbus1[$nsr] = $nameidx{$data{"BUS1"}};
	    }
	    if ($data{"BUS2"} eq "DCGROUND") {
		$srbus2[$nsr] = -1;      
	    } else {
		$srbus2[$nsr] = $nameidx{$data{"BUS2"}};
	    }
	    $srno[$nsr] = assign("NO",0);
	    $srtype[$nsr] = assign("TYPE",1);
	    $srr[$nsr] = assign("R",0);
	    $srl[$nsr] = assign("L",0);
	    $srx[$nsr] = assign("X",0);
	    $srncon[$nsr] = !assign("NCON",0);
	}

    } elsif (/^SHUNT/) {

	while ($firstline ne "END") {
	    %data = splitdata(1);
	    if ($data{"BUS1"} eq "END") { last; }
	    $nsh++;
	    $shbus[$nsh] = $nameidx{$data{"BUS1"}};
	    $vbsh[$nsh] = assign("UN",$kvb[$shbus[$nsh]]);
	    $psh[$nsh] = -assign("P",0)/$pbase;
	    $qsh[$nsh] = -assign("Q",0)/$pbase;
	    $shstatus[$nsh] = status();
	    $shno[$nsh] = assign("NO",0);
	}

    } elsif (/^LOAD/) {

	while ($firstline ne "END") {
	    %data = splitdata(1);
	    if ($data{"BUS1"} eq "END") { last; }
	    $npq++;
	    $pqbus[$npq] = $nameidx{$data{"BUS1"}};
	    $pqpl[$npq] = assign("P",0)/$pbase;
	    if (exists $data{"Q"}) {
		$pqql[$npq] = assign("Q",0)/$pbase;
	    } else {
		$h = assign("COSFI",1);
		$j = sqrt(1-$h*$h);
		$pqql[$npq] = $j*$pqpl[$npq]/$h;
	    }
	    $umin[$npq] = assign("UMIN",0.9);
	    $umax[$npq] = assign("UMAX",1.1);	
	    $loadstatus[$npq] = status();
	    $loadno[$npq] = assign("NO",0);
	}

    } elsif (/^POWER/) {

	while ($firstline ne "END") {

	    %data = splitdata(-1);
	    if (!$data{"BUS1"}) { print $firstline . "\n"; }
	    if ($data{"BUS1"} eq "END") { last; }
	    if (exists $data{"RTYPE"}) { $data{"RTYP"} = $data{"RTYPE"}; }
	    if ($data{"TYPE"} eq "NODE") {

		if ($data{"RTYP"} eq "UP") {

		    $npv++;
		    $ngen++;
		    $pvidx[$npv] = $ngen;
		    $pvbus[$npv] = $nameidx{$data{"BUS1"}};
		    $genbus[$ngen] = $pvbus[$npv]+1;
		    $genname[$ngen] = assign("NAME",$data{"BUS1"});
		    $pvpg[$npv] = assign("P",0)/$pbase;
		    $pvqt[$npv] = assign("QMAX",0)/$pbase;
		    $pvqb[$npv] = assign("QMIN",0)/$pbase;
		    $pvvs[$npv] = assign("U",0)/$kvb[$pvbus[$npv]];

		} elsif ($data{"RTYP"} eq "PQ") {

		    $npg++;
		    $ngen++;
		    $pgidx[$npg] = $ngen;
		    $pgbus[$npg] = $nameidx{$data{"BUS1"}};
		    $genbus[$ngen] = $pgbus[$npg]+1;
		    $genname[$ngen] = assign("NAME",$data{"BUS1"});
		    $pqpg[$npg] = assign("P",0)/$pbase;
		    $pqqg[$npg] = assign("Q",0)/$pbase;

		} elsif ($data{"RTYP"} eq "SW" || $data{"RTYP"} eq "UFI") {

		    $nsw++;
		    $ngen++;
		    $swidx[$nsw] = $ngen;
		    $swbus[$nsw] = $nameidx{$data{"BUS1"}};
		    $genbus[$ngen] = $swbus[$nsw]+1;
		    $genname[$ngen] = assign("NAME",$data{"BUS1"});
		    $swpg[$nsw] = assign("P",0)/$pbase;
		    $swqt[$nsw] = assign("QMAX",0)/$pbase;
		    $swqb[$nsw] = assign("QMIN",0)/$pbase;
		    $swvs[$nsw] = assign("U",$kvb[$swbus[$nsw]])/$kvb[$swbus[$nsw]];
		    $swfi[$nsw] = 0.017453*assign("FI",0);
		    if ($data{"RTYP"} eq "SW") {
			$swtype[$nsw] = 1;
		    } else {
			$swtype[$nsw] = 0;
		    }
		}

	    } elsif ($data{"TYPE"} eq "CONV") {

		$i = $cvidx{$data{"BUS1"}};
		
		if (($data{"RTYP"} eq "I") && $i >= 0) {
		    $cvtyp[$i] = 1;
		    $cvio[$i] = assign("IO",0);
		} elsif (($data{"RTYP"} eq "U") && $i >= 0) {
		    $cvtyp[$i] = 2;
		    $cvio[$i] = assign("UO",0);
		}
		$cvdi[$i] = assign("DI",0);
		$cvamin[$i] = assign("AMIN",0);
		$cvgmin[$i] = assign("GMIN",0);	

	    } elsif ($data{"TYPE"} eq "TREG") {

		$i = $lineno{$data{"BUS1"}.$data{"BUS2"}.assign("NO",1)};
		$h = $i-1;
		
		if (($data{"RTYP"} eq "TAUFI") && $i >= 0) {
		    
		    $treg[$h] = 1;
		    if ($tapside[$h] == 1) {
			$ratio[$h] = 1/assign("TAU",1);
		    } else {
			$ratio[$h] = assign("TAU",1);
		    }
		    $phas[$h] = 0.017453*assign("FI",0);
		    if (exists $data{"UNT"}) {
			$ratio[$h] = $data{"UNT"}/$kvb[$bustt[$h]];			
		    }

		} elsif (($data{"RTYP"} eq "UFI") && $i >= 0) { 

		    $treg[$h] = 2;
		    $linefi[$h] = assign("FI",0);
		    $linecnode[$h] = $nameidx{assign("CNODE",$data{"BUS2"})};
		    $linepar[$h] = assign("U",0);
		    
		} elsif (($data{"RTYP"} eq "AFI") && $i >= 0) { 

		    $treg[$h] = 3;
		    $linefi[$h] = assign("FI",0);
		    $linecnode[$h] = $nameidx{assign("CNODE",$data{"BUS2"})};
		    $lineconv[$h] = $cvidx{$data{"CONV"}}+1;
		    $linepar[$h] = assign("ALPHA",0);          

		} elsif (($data{"RTYP"} eq "GFI") && $i >= 0) { 

		    $treg[$h] = 4;
		    $linefi[$h] = assign("FI",0);
		    $linecnode[$h] = $nameidx{assign("CNODE",$data{"BUS2"})};
		    $lineconv[$h] = $cvidx{$data{"CONV"}}+1;
		    $linepar[$h] = assign("GAMMA",0);

		}

	    }
	}

    } elsif (/^COMMANDS/) {

	while (defined($_ = shift(@data))) {

	    chomp;
	    next if /^!/;
	    if (/^\$DISABLE/) { discom(); next; }
	    if (/^\$INCLUDE/) { include(); next; }
	    if (/^END/) { last; }

	    $_ =~ s/^\s*//;
	    
	    if (/^RUN/) { next; }
	    if (/^ALTER/) {
		
		@alter = split /\%\s*/ , $_;
		#print $alter[1] . "\n";

		if (/^LINE/) {
		    
		} elsif (/^TR2/) {
		    
		} elsif (/^TR3/) {
		    
		} elsif (/^SHUN/) {
		    
		} elsif (/^LOAD/) {
		    
		} elsif (/^PROD/) {
		    
		} elsif (/^ASYN/) {
		    
		}

		$_ =~ s/^ALTER\s+//;
		#print $_ . "\n";

	    }
	}
    }
}

# -----------------------------------------------------------------------
# scan DYNPOW/SIMPOW data file
# -----------------------------------------------------------------------

if (!$dynfile) {
    $ARGV[0] =~ s/\.optpow$/\.dynpow/;
    $file =~ s/\.optpow$/\.dynpow/;
} else {
    ($file,$dir) = fileparse($dynfile);
    $ARGV[0] = $dynfile;
}

print "Opening SIMPOW-DYNPOW file <$file>\n";

if (open(IN,$ARGV[0]) && !$nodyn) {

    @data = <IN>;
    close(IN) || die "Cannot close $file: $!\n";

    # read comments
    while (defined($_ = shift(@data))) {
	chomp;
	last if /^\*\*/;
	if (/^\$DISABLE/) { discom(); next; }
	if (/^\$INCLUDE/) { include(); next; }
	$ntitle++;
	$_ =~ s/^\!+//;
	$title[$ntitle] = $_;
    }

    # read data
    while (defined($_ = shift(@data))) {

	chomp;
	next if /^!/;
	if (/^\$DISABLE/) { discom(); }
	if (/^\$INCLUDE/) { include(); }
	$firstline = "NULL";

	if (/^GENERAL/) {	        # System bases

	    while ($firstline ne "END") {
		%data = splitdata(0);
		$fbase = assign("FN",$fbase);
	    }

	} elsif (/^CONTROL/) {	        # Control data

	    while ($firstline ne "END") {
		%data = splitdata(0);
		$symod = assign("SYMOD",$symod);
	    }

	} elsif (/^SYNCHRONOUS/) {	# Synchronous machines
	    
	    while ($firstline ne "END") {
		%data = splitdata(2);
		$nsyn++;
		$synbus[$nsyn] = $nameidx{$data{"BUS2"}};
		$gbas[$nsyn] = assign("SN",$pbase);
		$pf[$nsyn] = assign("PF",1);
		$qf[$nsyn] = assign("QF",1);
		$xd[$nsyn] = assign("XD",0);
		$xq[$nsyn] = assign("XQ",0);
		$xdp[$nsyn] = assign("XDP",0);
		$xqp[$nsyn] = assign("XQP",0);
		$xdb[$nsyn] = assign("XDB",0);
		$xqb[$nsyn] = assign("XQB",0);
		$ra[$nsyn] = assign("RA",0);
		$xl[$nsyn] = assign("XA",0);
		$td0p[$nsyn] = assign("TD0P",0);
		$tq0p[$nsyn] = assign("TQ0P",0);
		$td0b[$nsyn] = assign("TD0B",0);
		$tq0b[$nsyn] = assign("TQ0B",0);
		$mstt[$nsyn] = assign("H",5);
		$damp[$nsyn] = assign("DAMP",0);
		$gentype[$nsyn] = assign("TYPE",2);
		$gentype[$nsyn] =~ s/A//;
		if ($gentype[$nsyn] == 1) {
		    $gentype[$nsyn] = 6;
		} elsif ($gentype[$nsyn] == 2) {
		    $gentype[$nsyn] = 4;
		} elsif ($gentype[$nsyn] == 4) {
		    $gentype[$nsyn] = 2;
		}
		if ($tq0p[$nsyn] == 0) {
		    $gentype[$nsyn] = 3;
		}
		$synvreg[$nsyn] = assign("VREG",0);
	    }
	    
	} elsif (/^REGULATORS/) {

	    while ($firstline ne "END") {

		%data = splitdata(1);
		$type = assign("TYPE",1);

		if ($type eq "1") {
		    
		    $nexc++;
		    $exctype[$nexc] = 2;
		    $exccode[$nexc] = $data{"BUS1"};
		    $excka[$nexc] = assign("KA",0);
		    $excta[$nexc] = assign("TA",0);
		    $excte[$nexc] = assign("TE",0);
		    $exckf[$nexc] = assign("KF",0);
		    $exctf[$nexc] = assign("TF",0);
		    $exctr[$nexc] = assign("TR",0);
		    $excvrmax[$nexc] = assign("VRMAX",0);
		    $excvrmin[$nexc] = assign("VRMIN",0);
		    
		  } else {
		    
		    #print "Regulator type " . $type . " not supported.\n"
		      
		  }

	    }

	} # end scan components

    }

} elsif ($nodyn) {

    print "Force to ignore DYNPOW file.\n";

} else {

    print "Cannot open $file: $!\n";

}

# -----------------------------------------------------------------------
# open output data file
# -----------------------------------------------------------------------
print "Writing Matlab file <$outfile>\n";
open(OUT,">$ARGV[1]") || die "cannot open $outfile: $!\n";

# -----------------------------------------------------------------------
# write output data file
# -----------------------------------------------------------------------
print OUT "% File generated from SIMPOW data file.\n";
print OUT "% "."-" x 78 . "\n";
print OUT "% Author:   Federico Milano\n";
print OUT "% e-mail:   Federico.Milano\@uclm.es\n";
print OUT "% "."-" x 78 . "\n";
print OUT "% $title\n";
for ($i = 0; $i <= $ntitle; $i++) {
    print OUT "% $title[$i]\n";
}
print OUT "\n";

# -----------------------------------------------------------------------
# write Bus.con
# -----------------------------------------------------------------------
$format = "%4d %6.2f  %7.4f  %7.4f  %3d  %2d;\n";
$nbus >= 0 && print OUT "Bus.con = [ ...\n";
for ($i = 0; $i <= $nbus; $i++) {
    printf OUT $format,$i+1,$kvb[$i],$vol[$i],$ang[$i],$karea[$i],$kzone[$i];
}
$nbus >= 0 && printf OUT "   ];\n\n";

# -----------------------------------------------------------------------
# write SW.con
# -----------------------------------------------------------------------
$nsw >= 0 && print OUT "SW.con = [ ...\n";
for ($i = 0; $i <= $nsw; $i++) {
    $format = "%4d $pbase %6.2f %8.5f %8.5f %8.5f %8.5f 1.1 0.9 %8.5f %2d 1;\n";
    $h = $swbus[$i];
    printf OUT $format,$h+1,$kvb[$h],$swvs[$i],$swfi[$i],
    $swqt[$i],$swqb[$i],$swpg[$i],$swtype[$i];
}
$nsw >= 0 && printf OUT "   ];\n\n";


# -----------------------------------------------------------------------
# write PV.con
# -----------------------------------------------------------------------
$npv >= 0 && printf OUT "PV.con = [ ...\n";
$format = "%4d $pbase %6.2f " . "%8.5f " x 4 . "1.1 0.9 1 1;\n";
for ($i = 0; $i <= $npv; $i++) {
    $h = $pvbus[$i];
    printf OUT $format,$h+1,$kvb[$h],
    $pvpg[$i],$pvvs[$i],$pvqt[$i],$pvqb[$i];
}
$npv >= 0 && printf OUT "   ];\n\n";

# -----------------------------------------------------------------------
# write PQgen.con
# -----------------------------------------------------------------------
$npg >= 0 && printf OUT "PQgen.con = [ ...\n";
$format = "%4d $pbase %6.2f %8.5f %8.5f 1.1 0.9 1 1;\n";
for ($i = 0; $i <= $npg; $i++) {
    $h = $pgbus[$i];
    printf OUT $format,$h+1,$kvb[$h],$pqpg[$i],$pqqg[$i];
}
$npg >= 0 && printf OUT "   ];\n\n";

# -----------------------------------------------------------------------
# write PQ.con
# -----------------------------------------------------------------------
$npq >= 0 && printf OUT "PQ.con = [ ...\n";
$format = "%4d $pbase %6.2f %8.5f %8.5f %7.4f %7.4f 1 %2d;\n";
for ($i = 0; $i <= $npq; $i++) {
    $h = $pqbus[$i];
    printf OUT $format,$h+1,$kvb[$h],$pqpl[$i],$pqql[$i],
    $umax[$i],$umin[$i],$loadstatus[$i];
}
$npq >= 0 && printf OUT "   ];\n\n";

# -----------------------------------------------------------------------
# write Shunt.con
# -----------------------------------------------------------------------
$nsh >= 0 && print OUT "Shunt.con = [ ...\n";
$format = "%4d $pbase %6.2f $fbase %8.5f %8.5f %2d;\n";
for ($i = 0; $i <= $nsh; $i++) {
    if ($psh[$i] != 0 or $qsh[$i] != 0) {
	$h = $shbus[$i];
	printf OUT $format,$h+1,$vbsh[$i],$psh[$i],$qsh[$i],
	$shstatus[$i];
    }
}
$nsh >= 0 && printf OUT "   ];\n\n";

# -----------------------------------------------------------------------
# write Line.con
# -----------------------------------------------------------------------
if ($nline >= 0) {
    print OUT "Line.con = [ ...\n";
    $format = "%4d %4d %6.2f %6.2f $fbase 0 " . 
	"%8.5f " x 6 . "%7.3f %7.3f 0 %2d\n"; 
    # TRANSMISSION LINES FIRST ...
    for ($i = 0; $i <= $nline; $i++) {
	if ($kt[$i] == 0) {
	    printf OUT $format,$busfr[$i]+1,$bustt[$i]+1,
	    $tfsb[$i],$linevb[$i],$kt[$i],$rest[$i],
	    $reat[$i],$susc[$i],$ratio[$i],$phas[$i],
	    $imax[$i],$pmax[$i],$linestatus[$i];
	}
    }
    # ... AND TRANSFORMERS AT THE END
    for ($i = 0; $i <= $nline; $i++) {
	if ($kt[$i]) {
	    printf OUT $format,$busfr[$i]+1,$bustt[$i]+1,
	    $tfsb[$i],$linevb[$i],$kt[$i],$rest[$i],
	    $reat[$i],$susc[$i],$ratio[$i],$phas[$i],
	    $imax[$i],$pmax[$i],$linestatus[$i];
	}
    }
    print OUT "   ];\n\n";
}

# -----------------------------------------------------------------------
# write Conv.con
# -----------------------------------------------------------------------
if ($ncv == -2) { # skip converter data
    print OUT "Conv.con = [ ...\n";
    $format = "%4d %4d %4d %7.2f %7.2f %8.5f %8.5f " .
	"%2d %7.2f %8.5f %8.5f %8.5f;\n";
    for ($i = 0; $i <= $ncv; $i++) {
	printf OUT $format,$cvbus[$i]+1,$cvbusdc1[$i]+1,$cvbusdc2[$i]+1,
	$cvidn[$i],$cvudion[$i],$cvdx[$i],$cvdr[$i],$cvtyp[$i],
	$cvio[$i],$cvdi[$i],$cvamin[$i],$cvgmin[$i];
    }
    print OUT "   ];\n\n";
}

# -----------------------------------------------------------------------
# write Sreact.con
# -----------------------------------------------------------------------
if ($nsr == -2) { # skip series reactance data
    print OUT "Sreact.con = [ ...\n";
    $format = "%4d %4d %2d %2d %8.5f %8.5f %8.5f %2d;\n";
    for ($i = 0; $i <= $nsr; $i++) {
	printf OUT $format,$srbus1[$i]+1,$srbus2[$i]+1,$srno[$i],
	$srtype[$i],$srr[$i],$srl[$i],$srx[$i],$srncon[$i];
    }
    print OUT "   ];\n\n";
}

# -----------------------------------------------------------------------
# write Twt.con
# -----------------------------------------------------------------------
if ($ntw >= 0) {
    print OUT "Twt.con = [ ...\n";
    $format = "%4d %4d %4d %6.2f $fbase %6.2f %6.2f %6.2f " .
	"%8.5f " x 6 . "0 0 0 0 0 0 0 0 0 0 %2d;\n";
    for ($i = 0; $i <= $ntw; $i++) {
	printf OUT $format,$bus1[$i]+1,$bus2[$i]+1,$bus3[$i]+1,
	$twsb[$i],$vb1[$i],$vb2[$i],$vb3[$i],$r12[$i],$r13[$i],$r23[$i],
	$x12[$i],$x13[$i],$x23[$i],$twstatus[$i];
    }
    print OUT "   ];\n\n";
}

# -----------------------------------------------------------------------
# write Syn.con
# -----------------------------------------------------------------------
$nsyn >= 0 && print OUT "Syn.con = [ ...\n";
$format = "%4d %6.2f %6.2f $fbase %2d " . "%8.5f " x 14 . 
    " 0 0 %6.2f %6.2f 0 0 0 1 1;\n";
for ($i = 0; $i <= $nsyn; $i++) {
    $h = $synbus[$i];
    printf OUT $format,$h+1,$gbas[$i],$kvb[$h],$gentype[$i],
    $xl[$i],$ra[$i],$xd[$i],$xdp[$i],$xdb[$i],
    $td0p[$i],$td0b[$i],$xq[$i],$xqp[$i],$xqb[$i],$tq0p[$i],
    $tq0b[$i],$mstt[$i],$damp[$i],$pf[$i],$qf[$i];
}
$nsyn >= 0 && print OUT "   ];\n\n";

# -----------------------------------------------------------------------
# write Exc.con
# -----------------------------------------------------------------------
$nexc >= 0 && print OUT "Exc.con = [ ...\n";
$format = "%4d %2d " . "%8.5f " x 6 . "0 " . "%8.5f " x 2 . "0.0006 0.9 1;\n";
for ($i = 0; $i <= $nexc; $i++) {
    for ($h = 0; $h <= $nsyn; $h++) {
	if ($synvreg[$h] == $exccode[$i]) {
	    printf OUT $format,$h+1,$exctype[$i],$excvrmax[$i],
	    $excvrmin[$i],$excka[$i],$excta[$i],$exckf[$i],
	    $exctf[$i],$excte[$i],$exctr[$i];
	}
    }
}
$nexc >= 0 && print OUT "   ];\n\n";

# -----------------------------------------------------------------------
# write Bus.name
# -----------------------------------------------------------------------
if ($nbus >= 0) {
    print OUT "Bus.names = { ...\n";
    $h = ($nbus+1) % 5;
    if ($h == 0) { $h = 5; }
    if (($nbus+1) > 5) {
	for ($i = 0; $i <= $nbus-$h; $i+=5) {
	    print OUT "  '$busname[$i]'; '$busname[$i+1]'; " . 
		"'$busname[$i+2]'; '$busname[$i+3]'; '$busname[$i+4]';\n";
	}
    }
    print OUT "  ";
    for ($i = $nbus-$h+1; $i <= $nbus-1; $i++) {
	print OUT "'$busname[$i]'; ";
    }
    print OUT "'$busname[$nbus]'};\n\n";
}

# -----------------------------------------------------------------------
# write PV.name
# -----------------------------------------------------------------------
if ($npv == -2) { # skip PV names
    print OUT "PV.name = { ...\n";
    $h = ($npv+1) % 5;
    if ($h == 0) { $h = 5; }
    if (($npv+1) > 5) {
	for ($i = 0; $i <= $npv-$h; $i+=5) {
	    $j = $pvidx[$i];
	    print OUT "  '$genname[$j]'; '$genname[$j+1]'; " . 
		"'$genname[$j+2]'; '$genname[$j+3]'; '$genname[$j+4]';\n";
	}
    }
    print OUT "  ";
    for ($i = $npv-$h+1; $i <= $npv-1; $i++) {
	$j = $pvidx[$i];
	print OUT "'$genname[$j]'; ";
    }
    print OUT "'$genname[$pvidx[$npv]]'};\n\n";
}

# -----------------------------------------------------------------------
# write PQgen.name
# -----------------------------------------------------------------------
if ($npg == -2) { # skip PQgen names
    print OUT "PQgen.name = { ...\n";
    $h = ($npg+1) % 5;
    if ($h == 0) { $h = 5; }
    if (($npg+1) > 5) {
	for ($i = 0; $i <= $npg-$h; $i+=5) {
	    $j = $pgidx[$i];
	    print OUT "  '$genname[$j]'; '$genname[$j+1]'; " . 
		"'$genname[$j+2]'; '$genname[$j+3]'; '$genname[$j+4]';\n";
	}
    }
    print OUT "  ";
    for ($i = $npg-$h+1; $i <= $npg-1; $i++) {
	$j = $pgidx[$i];
	print OUT "'$genname[$j]'; ";
    }
    print OUT "'$genname[$pgidx[$npg]]'};\n\n";
}

# -----------------------------------------------------------------------
# write SW.name
# -----------------------------------------------------------------------
if ($nsw == -2) { # skip SW names
    print OUT "SW.name = { ...\n";
    $h = ($nsw+1) % 5;
    if ($h == 0) { $h = 5; }
    if (($nsw+1) > 5) {
	for ($i = 0; $i <= $nsw-$h; $i+=5) {
	    $j = $swidx[$i];
	    print OUT "  '$genname[$j]'; '$genname[$j+1]'; " . 
		"'$genname[$j+2]'; '$genname[$j+3]'; '$genname[$j+4]';\n";
	}
    }
    print OUT "  ";
    for ($i = $nsw-$h+1; $i <= $nsw-1; $i++) {
	$j = $swidx[$i];
	print OUT "'$genname[$j]'; ";
    }
    print OUT "'$genname[$swidx[$nsw]]'};\n\n";
}

# -----------------------------------------------------------------------
# write Conv.name
# -----------------------------------------------------------------------
if ($ncv == -2) { # skip Converter names
    print OUT "Conv.name = { ...\n";
    $h = ($ncv+1) % 5;
    if ($h == 0) { $h = 5; }
    if (($ncv+1) > 5) {
	for ($i = 0; $i <= $ncv-$h; $i+=5) {
	    print OUT "  '$cvname[$i]'; '$cvname[$i+1]'; " . 
		"'$cvname[$i+2]'; '$cvname[$i+3]'; '$cvname[$i+4]';\n";
	}
    }
    print OUT "  ";
    for ($i = $ncv-$h+1; $i <= $ncv-1; $i++) {
	print OUT "'$cvname[$i]'; ";
    }
    print OUT "'$cvname[$ncv]'};\n\n";
}

# -----------------------------------------------------------------------
# close output data file
# -----------------------------------------------------------------------
close(OUT) || die "Cannot close $ARGV[1]: $!\n";
print "Conversion completed.\n";

# -----------------------------------------------------------------------
# function that assigns file or default values
# -----------------------------------------------------------------------
sub assign {
    my $value = $_[1];
    if (exists $data{$_[0]}) {
	$value = $data{$_[0]};
    }
    return $value;
}

# -----------------------------------------------------------------------
# function that assigns the status of a component
# -----------------------------------------------------------------------
sub status {
    my $status;
    if (assign("NCON",0)) {
	$status = 0;
    } else {
	$status = 1;
    }
    return $status;
}

# -----------------------------------------------------------------------
# function that discards comment region in the data file
# -----------------------------------------------------------------------

sub discom {

    while (defined($_ = shift(@data))) { last if /^\$ENABLE/; }

}

# -----------------------------------------------------------------------
# function that takes care of the $INCLUDE statement
# -----------------------------------------------------------------------

sub include {

    my (@temp,@mydata);
    @temp = split /\s*[\s=]\s*/, $_;
    $temp[1] =~ tr/[A-Z]/[a-z]/; 
    $temp[1] =~ s/\\/\//g;
    #$temp[1] =~ s/\//$file_separator/g;
    $temp[1] = $dir . $temp[1];
    if (open(IN,$temp[1])) {
	print "Including file <" . $temp[1] . ">\n";  
	@mydata = <IN>;
	unshift @data , @mydata;
	close(IN);
    } else {
	print "Cannot open include file $temp[1]: $!\n";
    }
}

# -----------------------------------------------------------------------
# function that sorts hash values by their index value
# -----------------------------------------------------------------------
#sub byindex { 
#    my ($x,$y);
#    $x = $nodes{$a};
#    $y = $nodes{$b};
#    $x->{IDX} <=> $y->{IDX} 
#} 

# -----------------------------------------------------------------------
# function that returns the data in a hash {parameter,value}
# -----------------------------------------------------------------------
sub splitdata {

    my ($h,$i,@temp,%mydata);

    # assign firstline for the first time
    if ($firstline eq "NULL") {
	while (defined($_ = shift(@data))) {
	    chomp;
	    next if /^!/;
	    if (/^\$DISABLE/) { discom(); next; }
	    if (/^\$INCLUDE/) { include(); next; }
	    if (/^END/) {
		$firstline = "END";
		$mydata{"BUS1"} = "END";
		return %mydata;
	    }
	    $_ =~ s/^\s*//;
	    next if (!$_);
	    $firstline = $_;
	    last;
	}
    }

    $firstline =~ s/^\s*//;
    @temp = split /\s*[\s=]\s*/, $firstline;

    $h = shift;

    if ($h == -1) {
	for ($i = 1; $i <= @temp-1; $i++) {
	    if ($temp[$i] eq "TYPE") {
		if ($temp[$i+1] eq "NODE")   { $h = 1; }
		if ($temp[$i+1] eq "TREG")   { $h = 2; }	
		if ($temp[$i+1] eq "TR3")    { $h = 3; }
		if ($temp[$i+1] eq "REGION") { $h = 2; }
		if ($temp[$i+1] eq "CONV")   { $h = 1; }
		last;
	    }
	}
    } elsif ($h == -2) {
	$h = 2;
	for ($i = 1; $i <= @temp-1; $i++) {
	    if ($temp[$i] eq "NW") {
		$h = $temp[$i+1];
		last;
	    }
	}
    }

    for ($i=1; $i<=$h; $i++) { $mydata{"BUS" . $i} = shift(@temp); }
    for ($i = 0; $i <= @temp-1; $i+=2) {
	$mydata{$temp[$i]} = $temp[$i+1];
    }

    while (defined($_ = shift(@data))) {

	chomp;
	next if /^!/;
	if (/^\$DISABLE/) { discom(); next; }
	if (/^\$INCLUDE/) { include(); next; }
	if (/^END/) {
	    $firstline = "END";
	    last;
	}
	if (/^\s{0,3}\w+/) {
	    $firstline = $_;
	    last;
	}
	$_ =~ s/^\s*//;
	next if (!$_);
	@temp = split /\s*[\s=]\s*/, $_;	
	for ($i = 0; $i <= @temp-1; $i+=2) {
	    $mydata{$temp[$i]} = $temp[$i+1];
	}

    }
    return %mydata;
}
